

import { get, has, isArray } from "lodash-es";
import {ITree} from "./inter"
import {reactive,ref} from "vue"


export class Tree {
    constructor(){

    }
    //
    private HEAD:string[] = []
    private nodes = new Map<string,ITree.Node>();
    //
    // 树形数据
    tree:ITree.Tree = reactive([])
    // 当前节点
    currentId = ref("")
    // 已选节点列表
    selectIds:string[] = reactive([])
    // 初始化数据
    init(tree:ITree.Tree){
        //
        this.clear();
        //
        this.HEAD.length = 0;
        this.nodes.clear();
        this.tree.length = 0;
        //
        this.tree.push(...tree);
        //
        const f = (node:ITree.TreeNode,pid?:string) => {
            const {id,children} = node;
            const d:ITree.Node = {id}
            this.nodes.set(id,d)
            if(!pid){
                this.HEAD.push(id)
            }
            else{
                d.prev = pid
            }
            if(children){
                d.next = children.map(n => n.id)
                for(let n of children){
                    f(n,id)
                }
            }
        }
        //
        for(let n of tree){
            f(n)
        }
    }
    // 新增节点，插入新的节点
    addNode(pid:string):this
    addNode(index:number):this
    addNode(arg0?:string|number,arg1?:number){
        const id = this.newId();
        const node:ITree.Node = {id}
        const pid = typeof arg0 == 'string' ? arg0 : undefined;
        const index = typeof arg0 == 'number' ? arg0 : arg1;
        //
        let pnode:ITree.Node | undefined = undefined
        if(pid && this.nodes.has(pid)){
            node.prev = pid;
            pnode = this.nodes.get(pid)
        }
        if(pnode != undefined){
            if(pnode.next == undefined || !isArray(pnode.next)){
                pnode.next = []
            }
            const pl = pnode.next.length;
            const i = index && index < pl ? index : pl;
            pnode.next.splice(i,0,id)
        }
        else{
            const pl = this.HEAD.length;
            const i = index && index < pl ? index : pl;
            this.HEAD.splice(i,0,id)
        }
        //
        this.nodes.set(id,node);
        //
        return this;
    }
    // 修改，移动节点位置，
    update(id:string,pid:string):this
    update(id:string,index:number):this
    update(id:string,arg0:number|string,arg1?:string){
        const node = this.nodes.get(id);
        if(node){
            const pid = typeof arg0 == 'string' ? arg0 : arg1
            const list = pid ? this.nodes.get(pid)?.next : this.HEAD;
            const index = typeof arg0 == 'number' ? arg0 : list?.length;
            const pl = node.prev ? this.nodes.get(node.prev)?.next : this.HEAD;
            const i = pl ? pl.indexOf(node.id) : -1;
            const bool = list != undefined && index != undefined && index >=0 && pl != undefined && i >= 0;
            if(bool){
                // 移动节点，追加节点属性
                list.splice(index,0,node.id);
                // 在原节点的父节点中删除原节点
                pl.splice(i,1)
                // 修改节点的属性
                node.prev = pid;
            } 
        }
        return this;
    }
    // 删除节点 删除所有子节点
    removeNode(id:string,isDeep?:boolean){
        if(this.nodes.has(id)){
            const node = this.nodes.get(id) as ITree.Node;
            const pid = node.prev;
            const next = node.next;
            if(next && next.length > 0){
                if(isDeep){
                    for(const cid of next){
                        this.removeNode(cid) // 递归删除子节点
                    }
                }
                else{
                    throw new Error("当前节点有子节点，无法删除！")
                }
            }
            const plist = pid == undefined ? this.HEAD : this.nodes.get(pid)?.next;
            //
            const i = plist?.indexOf(id) || -1
            i >=0 && plist?.splice(i,1);
            this.nodes.delete(id);
        }
        return this;
    }
    // 批量删除节点
    removeNodes(ids:string[],isDeep?:boolean){
        for(const id of ids){
            try {
                this.removeNode(id,isDeep)
            } catch (error) {
                console.log("删除失败！: ",id," :==> ",error)
            }
        }
        return this;
    }
    // 刷新树的数据
    refresh(){
        const f = (ids:string[]) => {
            const l:ITree.Tree = [];
            for(let id  of ids){
                const node = this.nodes.get(id);
                if(node){
                    const children = node.next ? f(node.next) : undefined;
                    //
                    l.push({id,children})
                }
            }

            return l;
        }
        const list = f(this.HEAD);
        //
        this.tree.length = 0;
        this.tree.push(...list);
        return this
    }
    // 选择节点
    select(id:string){
        this.selectIds.push(id);
        return this;
    }
    // 清空已选节点
    clearSelect(){
        this.selectIds.length = 0;
        return this;
    }
    // 设置当前节点
    current(id:string){
        this.currentId.value = id;
        return this;
    }
    // 清空当前节点
    clearCurrent(){
        this.currentId.value = "";
        return this;
    }
    // 清空当前节点和已选节点
    clear(){
        this.clearCurrent().clearSelect();
        return this;
    }
    //

    private newId(){
        return crypto.randomUUID()
    }
    // 静态方法
    // 遍历
    static map<T>(tree:T[],option:ITree.Option = {},call:(node:ITree.Node<T>) => void){
        const {key='id',children='children',isLeaf} = option;
        const getKey = (data:T):string => {
            if(typeof key == 'string' && has(data,key)){
                return get(data,key)
            }
            if(typeof key == 'function'){
                return key(data)
            }
            return crypto.randomUUID();
        }
        const isleaf = (data:T) => {
            if(isLeaf == undefined){return get(data,children) == undefined || get(data,children).length == 0}
            if(typeof isLeaf == 'string'){return get(data,isLeaf) as boolean}
            if(typeof isLeaf == 'function'){return isLeaf(data)}
            return false;
        }
        //
        const head = tree.map(d => getKey(d)).filter(k => k != '');
        // 深度遍历
        const f = (ds:T[],p?:ITree.Node<T>) => {
            for(let i = 0,l = ds.length;i < l;i++){
                const d = ds[i];
                const cls:T[] = get(d,children) || [];
                const b = isleaf(d);
                //
                const id = getKey(d)
                const node:ITree.Node = {data:d,prev:p? p.id : undefined,id,next:b ? [] : undefined}
                if(p){
                    p.next?.push(id)
                }
                // 放到递归之前可以维护 list 的排序
                call(node)
                //
                if(!b && cls.length > 0){
                    f(cls,node)
                }
            }
        }
        //
        f(tree)
        //
        return head;
    }
    // 返回叶节点集合
    static leafs<T>(map:ITree.TreeMap<T>):ITree.Node<T>[] {
        // @ts-ignore
        const ids:string[] = map.get('Leafs') || [];
        const list = ids.filter(id => map.has(id)).map(id => map.get(id)) as ITree.Node<T>[]
        return list
    }
    // 树的扁平化，转化为关键字对象 head[],Map<any,T> 转换为双向链表结构 方便依据关键字查找 [head,map]
    static flatten<T>(tree:T[],option:ITree.Option = {}):ITree.TreeMap<T>{
        //
        const map:ITree.TreeMap<T> = new Map();
        const head:string[] = []
        const leafs:string[] = []
        //
        Tree.map(tree,option,(node) => {
            const id = node.id;
            if(node.prev == undefined){
                head.push(id)
            }
            if(node.next == undefined){
                leafs.push(id)
            }
            map.set(id,node);
        })
        //
        map.set("Head",head);
        map.set("Leafs",leafs)
        //
        return map;
    }
    // 生成树 由 双链表结构重新生成树 [head,map] => tree ,可以通过 children 字段来控制 生成树的子集属性名
    // static build<T>(map:ITree.TreeMap<T>,children='children',sourceTree?:T[]){
    //     const tree:T[] = sourceTree ? sourceTree : [];
    //     tree.length = 0;
    //     const head = map.get("Head");
    //     // for()
        
    // }
    // 过滤 多条件，或复杂条件过滤，支持自定义过滤
    static filter<T>(map:ITree.TreeMap<T>,fn:(node:ITree.Node<T>) => boolean){
        for(const v of map.values()){
            if(!Array.isArray(v)){
                const b = fn(v)
                if(!b){
                    // @ts-ignore
                    const ids:string[] = v.prev == undefined ? map.get("Head") : v.prev.next;
                    // @ts-ignore
                    const i = ids.indexOf(v.id)
                    //
                    ids.splice(i,1)
                }
            }
        }
    }
    // 排序，移动节点
    // static sort<T>(map:ITree.TreeMap<T>,id:string,index?:number,parent?:string){
    //     // @ts-ignore
    //     const ids:string[]|undefined = parent ? map.get(parent)?.next : map.get("Head") ;
    //     const i = index ? index : ids?.length
    // }
    // // 重置属性值 重置结构
    // static reset<T>(map:ITree.TreeMap<T>){

    // }
}